package com.suray.wcs.service.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.suray.system.run.ding.DingRobot;
import com.suray.wcs.res.enums.RgvStatus;
import com.suray.wcs.service.core.util.DateUtil;
import com.suray.wcs.service.enums.ElectricStatus;
import com.suray.wcs.service.enums.WcsExceptionType;
import com.suray.wcs.service.system.entity.ExceptionLogDB;
import com.suray.wcs.service.system.entity.RgvHeartLogDB;
import com.suray.wcs.service.system.mapper.ExceptionLogMapper;
import com.suray.wcs.service.system.service.IExceptionLogdbService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 操作日志 服务实现类
 * </p>
 *
 * @author cooper
 * @since 2019-06-26
 */
@Service
public class ExceptionLogServiceImpl extends ServiceImpl<ExceptionLogMapper, ExceptionLogDB> implements IExceptionLogdbService {
    @Autowired
    private ExceptionLogMapper exceptionLogMapper;
    static final Long INTERVAL_TIME = Long.valueOf(15);

    @Override
    public List<ExceptionLogDB> getExceptionLogs(ExceptionLogDB wcsexceptiondb) {
        LambdaQueryWrapper<ExceptionLogDB> queryWrapper = new LambdaQueryWrapper<>();
        if (!StringUtils.isEmpty(wcsexceptiondb.getTaskId())) {
            queryWrapper.like(ExceptionLogDB::getTaskId, wcsexceptiondb.getTaskId());
        }
        if (wcsexceptiondb.getExceptionType() != null) {
            queryWrapper.eq(ExceptionLogDB::getExceptionType, wcsexceptiondb.getExceptionType());
        }
        if (!StringUtils.isEmpty(wcsexceptiondb.getDeviceName())) {
            queryWrapper.like(ExceptionLogDB::getDeviceName, wcsexceptiondb.getDeviceName());
        }
        if (!StringUtils.isEmpty(wcsexceptiondb.getErrCode())) {
            queryWrapper.like(ExceptionLogDB::getErrCode, wcsexceptiondb.getErrCode());
        }
        if (!StringUtils.isEmpty(wcsexceptiondb.getParams().get("beginTime"))) {
            queryWrapper.ge(ExceptionLogDB::getCreateTime, wcsexceptiondb.getParams().get("beginTime"));
        }
        if (!StringUtils.isEmpty(wcsexceptiondb.getParams().get("endTime"))) {
            queryWrapper.le(ExceptionLogDB::getCreateTime, wcsexceptiondb.getParams().get("endTime"));
        }
        queryWrapper.orderByDesc(ExceptionLogDB::getCreateTime);
        return exceptionLogMapper.selectList(queryWrapper);
    }


    @Override
    public List<ExceptionLogDB> getWCSErrsLog(ExceptionLogDB wcsexceptiondb) {
        LambdaQueryWrapper<ExceptionLogDB> queryWrapper = new LambdaQueryWrapper<>();
        if (!StringUtils.isEmpty(wcsexceptiondb.getTaskId())) {
            queryWrapper.like(ExceptionLogDB::getTaskId, wcsexceptiondb.getTaskId());
        }
        if (wcsexceptiondb.getExceptionType() != null) {
            queryWrapper.eq(ExceptionLogDB::getExceptionType, wcsexceptiondb.getExceptionType());
        }
        if (!StringUtils.isEmpty(wcsexceptiondb.getDeviceName())) {
            queryWrapper.like(ExceptionLogDB::getDeviceName, wcsexceptiondb.getDeviceName());
        }
        if (!StringUtils.isEmpty(wcsexceptiondb.getErrCode())) {
            queryWrapper.eq(ExceptionLogDB::getErrCode, wcsexceptiondb.getErrCode());
        }
        if (wcsexceptiondb.getStartOccurredTime() != null) {
            queryWrapper.gt(ExceptionLogDB::getCreateTime, wcsexceptiondb.getStartOccurredTime());
        }
        if (wcsexceptiondb.getEndOccurredTime() != null) {
            queryWrapper.lt(ExceptionLogDB::getCreateTime, wcsexceptiondb.getEndOccurredTime());
        }
        queryWrapper.orderByAsc(ExceptionLogDB::getCreateTime);
        return exceptionLogMapper.selectList(queryWrapper);
    }


    @Override
    public String toStackTrace(Exception e) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            e.printStackTrace(pw);
            return sw.toString();
        } catch (Exception e1) {
            return "";
        }
    }


    /**
     * @param e             抛出的Exception
     * @param exceptionType {@link WcsExceptionType}
     * @param taskId        异常任务ID
     * @param deviceName    异常设备名
     * @param deviceStatus  出现异常时设备状态
     * @param errCode       异常码
     * @param witnessUser   异常时登录用户
     * @return true 插入成功
     */
    @Override
    public boolean addExceptionLog(Exception e, Integer exceptionType, Integer taskId,
                                   String deviceName, Integer deviceStatus, Integer errCode, String witnessUser) {
        DingRobot.pauseMessage(e.getMessage());
        ExceptionLogDB exceptionLogdb = new ExceptionLogDB();
        exceptionLogdb.setCreateTime(new Date());
        exceptionLogdb.setExceptionType(exceptionType);
        exceptionLogdb.setExceptionInfo(e.getMessage());
        if (taskId != null && taskId != 0) {
            exceptionLogdb.setTaskId(Integer.toString(taskId));
        }
        exceptionLogdb.setDeviceName(deviceName);
        exceptionLogdb.setDeviceStatus(deviceStatus);
        if (errCode != null) {
            exceptionLogdb.setErrCode(Integer.toString(errCode));
        }
        return save(exceptionLogdb);
    }

    /**
     * @param e             抛出的Exception
     * @param exceptionType {@link WcsExceptionType}
     * @param taskId        异常任务ID
     * @param deviceName    异常设备名
     * @param deviceStatus  出现异常时设备状态
     * @return true 插入成功
     */
    @Override
    public boolean addLowExceptionLog(String e, Integer exceptionType, Integer taskId,
                                      String deviceName, Integer deviceStatus) {
        ExceptionLogDB exceptionLogdb = new ExceptionLogDB();
        exceptionLogdb.setCreateTime(new Date());
        exceptionLogdb.setExceptionType(exceptionType);
        if (taskId != null && taskId != 0) {
            exceptionLogdb.setTaskId(Integer.toString(taskId));
        }
        exceptionLogdb.setDeviceName(deviceName);
        exceptionLogdb.setDeviceStatus(deviceStatus);
        return save(exceptionLogdb);
    }

    @Override
    public void deleteThreeDaysEpLog(Integer days) {
        exceptionLogMapper.deleteThreeDaysEpLog(days);
    }

    @Override
    public int deleteExceptionLogById(Long[] exceptionLogIds) {
        return exceptionLogMapper.deleteExceptionLogByIds(exceptionLogIds);
    }

    @Override
    public void cleanExceptionLog() {
        exceptionLogMapper.cleanExceptionLog();
    }

    @Override
    public List<Map<String, Object>> getExceptionDate(ExceptionLogDB exceptionLogDB) {
        List<Map<String, Object>> dataList = Lists.newArrayList();
        if (org.apache.commons.lang3.StringUtils.isBlank(exceptionLogDB.getDeviceName())) {
            return dataList;
        }
        List<ExceptionLogDB> exceptionLogDBList = getExceptionLogs(exceptionLogDB);
        Map<String, List<ExceptionLogDB>> sendTimeStrMap = Maps.newHashMap();
        Date sendTimeStart = (Date) exceptionLogDB.getParams().get("beginTime");
        if (CollectionUtils.isNotEmpty(exceptionLogDBList)) {
            //比较第一条故障日志的时间是否和开始时间一致
            //找出所有分钟内有心跳的记录，取第一条
            for (ExceptionLogDB exceptionLog : exceptionLogDBList) {
                Date createTime = exceptionLog.getCreateTime();
                String sendTimeStr = DateUtil.format(createTime, DateUtil.YD);
                if (sendTimeStrMap.containsKey(sendTimeStr)) {
                    List<ExceptionLogDB> exceptionLogDBS = sendTimeStrMap.get(sendTimeStr);
                    exceptionLogDBS.add(exceptionLog);
                } else {
                    List<ExceptionLogDB> exceptionLogsMap = Lists.newArrayList();
                    sendTimeStrMap.put(sendTimeStr, exceptionLogsMap);
                }
            }
        }
        fillDataList(sendTimeStart, dataList, sendTimeStrMap);
        return dataList;
    }

    private void fillDataList(Date sendTimeStart, List<Map<String, Object>> dataList, Map<String, List<ExceptionLogDB>> sendTimeStrMap) {
        for (int i = 0; i <= INTERVAL_TIME.intValue(); i++) {
            String sendTimeStr = DateUtil.format(sendTimeStart, DateUtil.YD);
            if (sendTimeStrMap.size() > 0 && sendTimeStrMap.containsKey(sendTimeStr)) {
                addMap(sendTimeStrMap.get(sendTimeStr), dataList, sendTimeStr);
            } else {
                addMap(null, dataList, sendTimeStr);
            }
            sendTimeStart = DateUtil.addDay(1, sendTimeStart);
        }
    }

    private void addMap(List<ExceptionLogDB> exceptionLogDBS, List<Map<String, Object>> dataList, String xValue) {
        if (exceptionLogDBS != null) {
            dataList.add(fillDataMap(exceptionLogDBS.size(), xValue));
        } else {
            dataList.add(fillDataMap(0, xValue));
        }
    }

    private Map<String, Object> fillDataMap(Integer battery, String xValue) {
        Map<String, Object> dataMap = Maps.newHashMap();
        dataMap.put("count", battery);
        dataMap.put("xValue", xValue);
        return dataMap;
    }

}
